#include "enpconfig.h"

using namespace CTLib;

#define MAIN_SECTION    "Global"

// int型
#define GETINT(section, name, value) \
    value = cfg.GetInt(section, name, &iRet); \
	if (iRet) \
	{ \
		CT_THROW(("[%s]%s failed %d", MAIN_SECTION, name, iRet)); \
	}

// char数组
#define GETSTR(section, name, value) \
    s = cfg.GetString(section, name, &iRet); \
	if (iRet) \
	{ \
		CT_THROW(("[%s]%s failed %d", MAIN_SECTION, name, iRet)); \
	} \
    iRet = ct_snprintf(CT_STRSIZE(value), "%s", s.c_str()); \
    if (iRet < 0) \
    { \
        CT_THROW(("[%s]%s too long, over %d", MAIN_SECTION, name, sizeof(value))); \
    }

// CTSizeString数组
#define GETSIZESTRING(section, name, value) \
    s = cfg.GetString(section, name, &iRet); \
	if (iRet) \
	{ \
		CT_THROW(("[%s]%s failed %d", MAIN_SECTION, name, iRet)); \
	} \
    iRet = value.Set("%s", s.c_str()); \
    if (iRet < 0) \
    { \
        CT_THROW(("[%s]%s too long, over %d", MAIN_SECTION, name, sizeof(value))); \
    }

// string
#define GETSTRING(section, name, value) \
    value = cfg.GetString(section, name, &iRet); \
	if (iRet) \
	{ \
		CT_THROW(("[%s]%s failed %d", MAIN_SECTION, name, iRet)); \
	}

void CEnpConfig::ClearZoneKey()
{
    ZoneKeyArray.Clear();
}

int CEnpConfig::GetIndexByZoneID(int iZoneID)
{
    for (int i = 0; i < ZoneKeyArray.Size(); ++i)
    {
        if (ZoneKeyArray[i]._iZoneID == iZoneID)
        {
            return i;
        }
    }

    return -1;
}

int CEnpConfig::GetIndexByWebID(int iWebID)
{
    for (int i = 0; i < ZoneKeyArray.Size(); ++i)
    {
        for (int j = 0; j < ZoneKeyArray[i]._aiWebID.Size(); ++j)
        {
            if (ZoneKeyArray[i]._aiWebID[j] == iWebID)
            {
                return i;
            }
        }
    }

    return -1;
}

int CEnpConfig::LoadConfig()
{
    CTConfig cfg;
    string s;
    int iRet = cfg.LoadConfig(FILE_CONFIG);
    if (iRet)
    {
        CT_THROW(("LoadConfig failed: %d", iRet));
    }

    GETSIZESTRING(MAIN_SECTION, "MgrShmKey", MgrShmKey);

    GETINT(MAIN_SECTION, "EnpStreamSize", FrontEndShmSize);

    FrontEndShmKeyArray.m_iUsedCount = FrontEndShmKeyArray.GetCount();
    FrontEndSocketArray.m_iUsedCount = FrontEndSocketArray.GetCount();
    BackEndSocketArray.m_iUsedCount = BackEndSocketArray.GetCount();

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey", FrontEndShmKeyArray[0]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket", FrontEndSocketArray[0]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket", BackEndSocketArray[0]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_1", FrontEndShmKeyArray[1]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_1", FrontEndSocketArray[1]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_1", BackEndSocketArray[1]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_2", FrontEndShmKeyArray[2]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_2", FrontEndSocketArray[2]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_2", BackEndSocketArray[2]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_3", FrontEndShmKeyArray[3]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_3", FrontEndSocketArray[3]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_3", BackEndSocketArray[3]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_4", FrontEndShmKeyArray[4]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_4", FrontEndSocketArray[4]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_4", BackEndSocketArray[4]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_5", FrontEndShmKeyArray[5]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_5", FrontEndSocketArray[5]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_5", BackEndSocketArray[5]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_6", FrontEndShmKeyArray[6]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_6", FrontEndSocketArray[6]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_6", BackEndSocketArray[6]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_7", FrontEndShmKeyArray[7]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_7", FrontEndSocketArray[7]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_7", BackEndSocketArray[7]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_8", FrontEndShmKeyArray[8]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_8", FrontEndSocketArray[8]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_8", BackEndSocketArray[8]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_9", FrontEndShmKeyArray[9]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_9", FrontEndSocketArray[9]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_9", BackEndSocketArray[9]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_10", FrontEndShmKeyArray[10]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_10", FrontEndSocketArray[10]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_10", BackEndSocketArray[10]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_11", FrontEndShmKeyArray[11]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_11", FrontEndSocketArray[11]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_11", BackEndSocketArray[11]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_12", FrontEndShmKeyArray[12]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_12", FrontEndSocketArray[12]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_12", BackEndSocketArray[12]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_13", FrontEndShmKeyArray[13]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_13", FrontEndSocketArray[13]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_13", BackEndSocketArray[13]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_14", FrontEndShmKeyArray[14]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_14", FrontEndSocketArray[14]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_14", BackEndSocketArray[14]);

    GETSIZESTRING(MAIN_SECTION, "EnpStreamKey_15", FrontEndShmKeyArray[15]);
    GETSIZESTRING(MAIN_SECTION, "EnpFrontEndSocket_15", FrontEndSocketArray[15]);
    GETSIZESTRING(MAIN_SECTION, "EnpBackEndSocket_15", BackEndSocketArray[15]);

	GETINT(MAIN_SECTION, "RecvBufferSize", RecvBufferSize);
	GETINT(MAIN_SECTION, "SendBufferSize", SendBufferSize);
	GETINT(MAIN_SECTION, "BufferCount", BufferCount);

	GETINT(MAIN_SECTION, "SocketMaxCount", SocketMaxCount);
	GETINT(MAIN_SECTION, "ListenCount", ListenArray.m_iUsedCount);

    CTSizeString<32> section;
    int iTemp = 0;
    for (int i = 0; i < ListenArray.m_iUsedCount; ++i)
    {
        section.Set("Listen%d", i + 1);

        GETSIZESTRING(section(), "ListenIP", ListenArray[i].m_szListenIP);

        GETINT(section(), "ListenPort", iTemp);
        ListenArray[i].m_unListenPort = static_cast<unsigned short>(iTemp);

        GETINT(section(), "IdleTimeout", ListenArray[i].m_uiIdleTimeout);

        GETSTRING(section(), "Package", s);
        CTStringUtils::TrimLeft(s, "\t\r\n ");
        CTStringUtils::TrimRight(s, "\t\r\n ");
        if (CTStringUtils::CompareNoCase(s, "http") == 0)
        {
            ListenArray[i].m_stPackageType = enp_package_http;
            ListenArray[i].m_ucDecodeMethod = CODE_HTTP;
        }
        else if (CTStringUtils::CompareNoCase(s, "protobuf") == 0)
        {
            ListenArray[i].m_stPackageType = enp_package_protobuf;
            ListenArray[i].m_ucDecodeMethod = CODE_PROTOBUF;

            // 读取安全策略文件
            GETSTRING(section(), "PolicyFile", s); // 读取文件的路径
            string strFile;
            iRet = CTFileUtils::ReadFile(s.c_str(), strFile);
            if (iRet)
            {
                CT_THROW(("[%s]Read Policy File failed", section()));
            }

            ListenArray[i].m_stBufferofPolicy.Append(strFile.c_str(),
                strFile.length() + 1);
        }
		else if (CTStringUtils::CompareNoCase(s, "binary") == 0)
        {
            ListenArray[i].m_stPackageType = enp_package_binary;
            ListenArray[i].m_ucDecodeMethod = CODE_BIN;
        }
        else if (CTStringUtils::CompareNoCase(s, "string") == 0)
        {
            ListenArray[i].m_stPackageType = enp_package_string;
            ListenArray[i].m_ucDecodeMethod = CODE_STRING;
        }
        else if (CTStringUtils::CompareNoCase(s, "encrypted") == 0)
        {
            ListenArray[i].m_stPackageType = enp_package_encrypted;
            ListenArray[i].m_ucDecodeMethod = CODE_ENCRYPTED;

            // 读取安全策略文件
            GETSTRING(section(), "PolicyFile", s); // 读取文件的路径
            string strFile;
            iRet = CTFileUtils::ReadFile(s.c_str(), strFile);
            if (iRet)
            {
                CT_THROW(("[%s]Read Policy File failed", section()));
            }

            ListenArray[i].m_stBufferofPolicy.Append(strFile.c_str(),
                strFile.length() + 1);
        }
        else if (CTStringUtils::CompareNoCase(s, "flash") == 0)
        {
            ListenArray[i].m_stPackageType = enp_package_flash;
            ListenArray[i].m_ucDecodeMethod = CODE_STRING;

            // 读取安全策略文件
            GETSTRING(section(), "PolicyFile", s); // 读取文件的路径
            string strFile;
            iRet = CTFileUtils::ReadFile(s.c_str(), strFile);
            if (iRet)
            {
                CT_THROW(("[%s]Read Policy File failed", section()));
            }

            ListenArray[i].m_stBufferofPolicy.Append(strFile.c_str(),
                strFile.length() + 1);
        }
        else
        {
            CT_THROW(("[%s]Package is not match: %s", section(), s.c_str()));
        }


        ///////////////编码方式///////////////////////////////////////////////////////
        GETSTRING(section(), "EncodeType", s);
        CTStringUtils::TrimLeft(s, "\t\r\n ");
        CTStringUtils::TrimRight(s, "\t\r\n ");
        if (CTStringUtils::CompareNoCase(s, "http") == 0)
        {
            ListenArray[i].m_ucEncodeMethod = CODE_HTTP;
        }
        else if (CTStringUtils::CompareNoCase(s, "protobuf") == 0)
        {
            ListenArray[i].m_ucEncodeMethod = CODE_PROTOBUF;
        }
		else if (CTStringUtils::CompareNoCase(s, "binary") == 0)
        {
            ListenArray[i].m_ucEncodeMethod = CODE_BIN;
        }
        else if (CTStringUtils::CompareNoCase(s, "string") == 0)
        {
            ListenArray[i].m_ucEncodeMethod = CODE_STRING;
        }
        else if (CTStringUtils::CompareNoCase(s, "json") == 0)
        {
            ListenArray[i].m_ucEncodeMethod = CODE_JSON;
        }
        else
        {
            CT_THROW(("[%s]EncodeType is not match", section()));
        }

    }

    int iAdminPort = 0;
    GETSIZESTRING(MAIN_SECTION, "AdminHost", AdminHost);
    GETINT(MAIN_SECTION, "AdminPort", iAdminPort);
    AdminPort = (unsigned short)(iAdminPort & 0xFFFF);

    //流量控制配置
    GETINT(MAIN_SECTION, "MaxConnect", MaxConnect);
    GETINT(MAIN_SECTION, "NewConnCheckInterval", NewConnCheckInterval);
    GETINT(MAIN_SECTION, "NewConnMax", NewConnMax);
    GETINT(MAIN_SECTION, "SendUpCheckInterval", SendUpCheckInterval);
    GETINT(MAIN_SECTION, "SendUpMax", SendUpMax);
    GETINT(MAIN_SECTION, "StopAccecptInterval", StopAccecptInterval);

	return LoadLogConfig();
}

int CEnpConfig::ReloadConfig()
{
	// 目前重读配置就是更新Log的配置
	return LoadLogConfig();
}

int CEnpConfig::LoadLogConfig()
{
    string s;
	CTConfig cfg;
	int iRet = cfg.LoadConfig(FILE_CONFIG);
	if (iRet)
	{
		CT_THROW(("LoadConfig failed: %d", iRet));
	}

    int iLogFileNum = 0, iLogFileSize = 0;
	GETINT(MAIN_SECTION, "LogFileNum", iLogFileNum);
	GETINT(MAIN_SECTION, "LogFileSize", iLogFileSize);
	CT_NLOG->Init(ENamed, NULL, FILE_NORMALLOG, iLogFileSize, iLogFileNum);
	CT_ELOG->Init(ENamed, NULL, FILE_ERRORLOG, iLogFileSize, iLogFileNum);
	CT_STAT->Init(ENamed, NULL, FILE_STATLOG, iLogFileSize, iLogFileNum);
	CT_STAT->SetFormat(ETime|ENewLine);

	// 设置filter
    string str;
	GETSTRING(MAIN_SECTION, "LogFormat", str)
	CT_NLOG->SetFormatByStr(str.c_str());
	CT_ELOG->SetFormatByStr(str.c_str());

	// 设置filter
	GETSTRING(MAIN_SECTION, "LogFilter", str)
	CT_NLOG->SetFilterByStr(str.c_str());
	CT_ELOG->SetFilterByStr(str.c_str());

	CT_INFO(("LogFormat=%d LogFilter=%d", CT_NLOG->GetFormat(), CT_NLOG->GetFilter()));

    ClearZoneKey();

	GETINT(MAIN_SECTION, "ZoneIDCount", ZoneKeyArray.m_iUsedCount);

    int iIntTmp = 0;
    CTSizeString<32> section;
    for (int i = 0; i < ZoneKeyArray.m_iUsedCount; ++i)
    {
        section.Set("ZoneKey%d", i + 1);

        GETSTRING(section(), "ZoneID", s);
        CTStringUtils::RemoveNot(s, "0123456789");
        iIntTmp = CTStringUtils::StrToInt<int>(s.c_str());
        if (iIntTmp > 0)
        {
            ZoneKeyArray[i]._iZoneID = iIntTmp;
        }
        else
        {
            continue;
        }

        GETSTRING(section(), "ServerID", s);
        CTStringUtils::RemoveNot(s, "0123456789|");
        vector<string> vKeyVal;
        CTStringUtils::Split(s, "|", vKeyVal);
        for (size_t j = 0; j < vKeyVal.size(); ++j)
        {
            iIntTmp = CTStringUtils::StrToInt<int>(vKeyVal[j].c_str());
            if (iIntTmp > 0)
            {
                ZoneKeyArray[i]._aiWebID.AddOneItem(iIntTmp);
            }
        }
    }

    return 0;
}

